import { Buffer } from 'node:buffer';
import crypto from 'crypto';
import express from 'express';


const WEBHOOK_TIMESTAMP_THRESHOLD_SECONDS = 30;

const webhookSignatureKey = process.env.WEBHOOK_SIGNATURE_KEY;
if (!webhookSignatureKey) {
    throw new Error('Environment variable WEBHOOK_SIGNATURE_KEY is not set');
}


/**
* Verifies signature of webhook/callback request and throws Error f signature is not valid.
*
* @param {string} timestampHeader Webhook-Timestamp header value
* @param {string} signatureHeader Webhook-Signature header value
* @param {crypto.BinaryLike} body raw body data
* @throws Error if signature is not valid
*/
const verifySignature = (timestampHeader, signatureHeader, body) > {

    const timestamp = Number(timestampHeader);
    if (Number.isNaN(timestamp)) {
        throw new Error('Webhook-Timestamp has invalid format');
    }
    if (Date.now() / 1000 - timestamp > WEBHOOK_TIMESTAMP_THRESHOLD_SECONDS) {
        throw new Error('Webhook-Timestamp exceed lifetime threshold');
    }

    const computedSignature = crypto.createHmac('sha256', webhookSignatureKey)
        .update(timestampHeader)
        .update('.')
        .update(body)
        .digest();

    for (const signatureRecord of signatureHeader.split(',')) {
        if (!signatureRecord.startsWith('v1=')) {
            continue;
        }
        const signatureBuffer = Buffer.from(signatureRecord.slice('v1='.length), 'hex');
        if (computedSignature.length === signatureBuffer.length
            && crypto.timingSafeEqual(computedSignature, signatureBuffer)) {
            return; // signature is correct
        }
    }
    throw new Error('Invalid signature');
}


const app = express();

app.post('/webhook',
    express.json({
        type: 'application/json',

        verify: (req, res, buf) => {
            let timestampHeader, signatureHeader;
            try {
                timestampHeader = req.get('Webhook-Timestamp');
                if (!timestampHeader) {
                    throw new Error('Required header Webhook-Timestamp is missing');
                }

                signatureHeader = req.get('Webhook-Signature');
                if (!signatureHeader) {
                    throw new Error('Required header Webhook-Signature is missing');
                }
            } catch (err) {
                res.status(400).send(err.message);
                throw err;
            }

            try {
                verifySignature(timestampHeader, signatureHeader, buf);
            } catch (err) {
                res.status(401).send(err.message);
                throw err;
            }
        }
    }),
    (req, res) => {

        // handle request

        res.sendStatus(200);
    }
);


app.listen(3000);